package org.budo.support.servlet.filter.resource.classpath;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.time.Time;
import org.springframework.core.io.ClassPathResource;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Getter
@Setter
@Slf4j
public abstract class BudoClassPathResourceFilter implements Filter {
    /**
     * 静态资源缓存过期时间，单位秒
     */
    private static final Integer RESOURCE_EXPIRES_IN = 5 * 60;

    private String root;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("#35 init, this=" + this);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String resourcePath = this.requestUriToResourcePath(request);

        if (this.handleResource(request, response, resourcePath)) {
            return;
        }

        chain.doFilter(request, response);
    }

    protected boolean handleResource(HttpServletRequest request, HttpServletResponse response, String resourcePath) throws IOException {
        ClassPathResource resource = new ClassPathResource(resourcePath);
        if (!resource.exists()) {
            return false;
        }

        this.setHeaders(request, response, resourcePath);

        IoUtil.write(resource.getInputStream(), response.getOutputStream());
        return true;
    }

    protected void setHeaders(HttpServletRequest request, HttpServletResponse response, String resourcePath) {
        if (StringUtil.endsWithIgnoreCase(resourcePath, ".css")) {
            response.setContentType("text/css");
        }

        this.setResourceExpiresIn(request, response);
    }

    private void setResourceExpiresIn(HttpServletRequest request, HttpServletResponse response) {
        if (request.getServerName().equalsIgnoreCase("localhost")) {
            return;
        }

        this.doSetResourceExpiresIn(response);
    }

    private void doSetResourceExpiresIn(HttpServletResponse response) {
        response.setHeader("Cache-Control", "public"); // Cache-Control来控制页面的缓存与否,public:浏览器和缓存服务器都可以缓存页面信息；
        response.setHeader("Pragma", "Pragma"); // Pragma:设置页面是否缓存，为Pragma则缓存，no-cache则不缓存

        Long nowTime = Time.now().toMilliSeconds();
        response.setDateHeader("Last-Modified", nowTime); // Last-Modified:页面的最后生成时间
        response.setDateHeader("Expires", nowTime + (RESOURCE_EXPIRES_IN * 1000)); // Expires:过时期限值
    }

    /**
     * @param requestURI 请求路径
     * @return 资源文件路径
     */
    protected abstract String requestUriToResourcePath(HttpServletRequest request);

    @Override
    public void destroy() {
        log.warn("#81 destroy, this=" + this);
    }
}
